#include "../inc/BufferIPC.hpp"
#include "../inc/DeviceObj.hpp"
#include "NodeClient.h"
#include <exception>
#include <thrift/Thrift.h>
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/protocol/TProtocol.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TSocket.h>
#include <thrift/transport/TTransport.h>

BufferIPC::BufferIPC() {
  broadcast.funcStartShot = [this](std::string UUID) {
    auto ptr = DeviceList.find(UUID);
    if (ptr == DeviceList.end())
      return;
    ptr->second->UpdateFormat();
  };
}

void BufferIPC::Boot(std::string addr, long clientport, long broadcastport) {
  // broadcast.Boot(std::format("tcp://{}:{}", addr, broadcastport));
  std::shared_ptr<apache::thrift::transport::TTransport> socket(
      new apache::thrift::transport::TSocket(addr, clientport));
  std::shared_ptr<apache::thrift::transport::TTransport> transport(
      new apache::thrift::transport::TBufferedTransport(socket));
  std::shared_ptr<apache::thrift::protocol::TProtocol> protocol(
      new apache::thrift::protocol::TBinaryProtocol(transport));
  client = new Thrift::NodeClientClient(protocol);
  try {
    transport->open();
  } catch (const apache::thrift::TException &e) {
    throw;
  }
}

std::deque<std::string> BufferIPC::GetDeviceList() {

  std::set<std::string> idlist;
  client->GetAllDevice(idlist);
  for (const auto &i : idlist) {
    if (DeviceList.find(i) != DeviceList.end())
      continue;
    DeviceObj *newobj;
    try {
      newobj = new DeviceObj(client, i);
    } catch (const std::exception &e) {
      throw;
    }
    DeviceList.insert({i, newobj});
  }

  std::deque<std::string> ret;
  for (auto &[ID, Obj] : DeviceList)
    ret.push_back(ID);
  return ret;
}

DeviceObj *BufferIPC::GetDevice(const std::string &UUID) {
  auto ptr = DeviceList.find(UUID);
  if (ptr == DeviceList.end())
    return nullptr;
  return ptr->second;
}

BufferIPC::~BufferIPC() {
  for (auto &[id, obj] : DeviceList)
    delete obj;
}
